using System;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Xml.Serialization;

using System.Security;
using System.Security.Policy;
using System.Security.Principal;
using System.Security.Permissions;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Administration;
using System.Text.RegularExpressions;

using System.Data;
using System.Data.SqlClient;

using System.Net.Mail;
using EAT.Common;


namespace EAT.CreateSiteCollection
{
    [Guid("5B55E39C-BBE4-42ee-92E6-AF956470E80A")]
    public class CreateSiteCollection : System.Web.UI.WebControls.WebParts.WebPart
    {
        [DllImport("advapi32.dll")]
        static extern bool RevertToSelf();

        SqlManager SqlM;
        protected EAT.Common.Provision Provision;

        private TextBox SiteURL;
        private TextBox SiteTitle;
        private TextBox SiteDesc;
        private ListBox SiteTemplate;
        private TextBox Justification;
        private Button buttonCreateSite;
        private Label TextLabel;

        public CreateSiteCollection()
        {
            this.ExportMode = WebPartExportMode.All;
            Provision = new Common.Provision();
            SqlM = new SqlManager();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write(Resources.Instructions);
            writer.Write("<table border=\"1\" align=\"center\" style=\"ms-authoringcontrols\">");

            writer.Write("<tr><td valign=\"top\" width=\"40%\">" + Resources.URLInstructions + "</td><td valign=\"top\">");
            SiteURL.RenderControl(writer);

            writer.Write("</td></tr><tr><td valign=\"top\" width=\"40%\">" + Resources.TitleInstructions + "</td><td valign=\"top\">");
            SiteTitle.RenderControl(writer);

            writer.Write("</td></tr><tr><td valign=\"top\" width=\"40%\">" + Resources.DescriptionInstructions + "</td><td valign=\"top\">");
            SiteDesc.RenderControl(writer);

            writer.Write("</td></tr><tr><td valign=\"top\" width=\"40%\">" + Resources.TemplateInstructions + "</td><td valign=\"top\">");
            SiteTemplate.RenderControl(writer);

            writer.Write("</td></tr><tr><td valign=\"top\" width=\"40%\">" + Resources.JustificationInstructions + "</td><td valign=\"top\">");
            Justification.RenderControl(writer);

            writer.Write("</td></tr><tr><td colspan=2>");
            buttonCreateSite.RenderControl(writer);
            writer.Write("</td></tr></table>");

            writer.Write("<br>");
            TextLabel.RenderControl(writer);
        }

        protected override void CreateChildControls()
        {
            SiteURL = new TextBox();
            SiteURL.ID = Resources.URLId;
            SiteURL.ToolTip = Resources.URLTip;
            SiteURL.Width = 500;
            this.Controls.Add(SiteURL);

            SiteTitle = new TextBox();
            SiteTitle.ID = Resources.TitleId;
            SiteTitle.ToolTip = Resources.TitleTip;
            SiteTitle.Width = 500;
            this.Controls.Add(SiteTitle);

            SiteDesc = new TextBox();
            SiteDesc.ID = Resources.DescriptionId;
            SiteDesc.ToolTip = Resources.DescriptionTip;
            SiteDesc.Width = 500;
            this.Controls.Add(SiteDesc);

            SiteTemplate = new ListBox();
            SiteTemplate.ID = Resources.TemplateId;
            SiteTemplate.ToolTip = Resources.TemplateTip;
            SiteTemplate.Width = 500;
            this.Controls.Add(SiteTemplate);

            SPWeb web = SPControl.GetContextWeb(System.Web.HttpContext.Current);
            using (SPSite site = new SPSite(web.Url.ToString()))
            {
                SPWebTemplateCollection webTemplates = site.GetWebTemplates((uint)web.Locale.LCID);
                foreach (SPWebTemplate template in webTemplates)
                {
                    SiteTemplate.Items.Add(template.Title);
                }
                SiteTemplate.Items[1].Selected = true;
            }
            Justification = new TextBox();
            Justification.ID = Resources.JustificationId;
            Justification.ToolTip = Resources.JustificationTip;
            Justification.TextMode = TextBoxMode.MultiLine;
            Justification.Rows = 4;
            Justification.Width = 500;
            Justification.MaxLength = 1000;
            this.Controls.Add(Justification);


            buttonCreateSite = new Button();
            buttonCreateSite.Text = Resources.ButtonText;
            buttonCreateSite.ToolTip = Resources.ButtonTip;
            buttonCreateSite.Click += new EventHandler(CreateSite_Click);
            this.Controls.Add(buttonCreateSite);

            TextLabel = new Label();
            TextLabel.Text = " ";
            TextLabel.ToolTip = Resources.TextTip;
            this.Controls.Add(TextLabel);


        }

        private bool ContainsIllegalCharacters(
                         string Text
                         )
        {
            if (Text != null)
            {
                if (Text.IndexOfAny("/\\:*?\"<>|#\t{}%~&][,@+=;'".ToCharArray()) == -1)
                    return false;
                else
                    return true;
            }
            else
            {
                return false;
            }

        }
        void CreateSite_Click(object sender, EventArgs e)
        {
            
            if (SiteURL.Text.Trim().Length < 1)
            {
                TextLabel.Text = Resources.BlankURLMessage;
                return;
            }

            if (ContainsIllegalCharacters(@SiteURL.Text))
            {
                TextLabel.Text = Resources.URLIllegalCharactersMessage;
                return;
            }

            // Does this site already exist?
            SPWeb web = SPControl.GetContextWeb(System.Web.HttpContext.Current);
            SPWebApplication spWebApp = SPWebApplication.Lookup(new Uri(web.Url));

            string[] allNames = spWebApp.Sites.Names;
            string shortURL = "sites/" + (SiteURL.Text.Trim().ToLower());
            
            foreach (string name in allNames)
            {
                if (name.ToLower().Equals(shortURL))
                {
                    TextLabel.Text = Resources.URLExistsMessage;
                    return;
                }
            }

            // Get the template selected by the user
            string templateTitle = HttpUtility.HtmlEncode(SiteTemplate.SelectedItem.Text);
            string templateName = null;

            using (SPSite site = new SPSite(web.Url.ToString()))
            {
                SPWebTemplateCollection webTemplates = site.GetWebTemplates((uint)web.Locale.LCID);

                foreach (SPWebTemplate template in webTemplates)
                {
                    if (template.Title.Equals(templateTitle))
                    {
                        templateName = template.Name;
                    }
                }
            }

            // Is there a group name in the config?
            if (SqlM.GetEntry("Config", "SCWorkflowApprovers").Length > 0)
            {
                CreateSiteWorkflow(templateName, shortURL);
            }
            else
            {
                SPHelper SPH = new SPHelper();
                //string SiteUrl = "/sites/" + HttpUtility.UrlEncode(SiteURL.Text);

                try
                {
                    SPH.CreateCollaborationSite(
                            //SiteUrl,
                            shortURL,
                            HttpUtility.HtmlEncode(SiteTitle.Text),
                            HttpUtility.HtmlEncode(SiteDesc.Text),
                            web.CurrentUser,
                            templateName
                            );

                    TextLabel.Text = String.Format(Resources.SiteCreatedMessage, HttpUtility.HtmlEncode(SiteTitle.Text));
                }
                catch (Exception ex)
                {
                    TextLabel.Text = ex.Message;
                }
            }
        }

        void CreateSiteWorkflow(string templateName, string newUrl)
        {

            string[] Values = new string[8] ;
            
            //
            // We create an array of strings that will hold the values entered
            // by the user. These will then be handed off to a helper function which
            // will store the strings in the DB.
            
            // First the site URL (relative)
            SPWeb web = SPControl.GetContextWeb(System.Web.HttpContext.Current);

            // check the DB and make sure this site url is not already requested
            if (!Provision.IsUrlAvailable(newUrl))
            {
                TextLabel.Text = Resources.WorkflowCantBeCreatedMessage;
                return;
            }

            Values[0] = newUrl;

            Values[1] = HttpUtility.HtmlEncode(SiteTitle.Text.Trim());
            Values[2] = HttpUtility.HtmlEncode(SiteDesc.Text.Trim());
 
            // requester
            Values[3] = HttpUtility.HtmlEncode(Context.User.Identity.Name);

            // request time stamp
            DateTime dt = DateTime.Now;
            Values[4] = dt.ToString();

            // justification
            Values[5] = HttpUtility.HtmlEncode(Justification.Text);

            // status
            Values[6] = "Pending";

            // template
            Values[7] = templateName;

            NewWorkflowItem(Values);

            //
            // The current user can't usually send e-mail, so revert to process identity
            //
            WindowsIdentity objOriginalUser = WindowsIdentity.GetCurrent();
            RevertToSelf();
            WindowsIdentity.GetCurrent().Impersonate();

            MailMessage msg = new MailMessage();
            //
            // Send email to the SP group that is responsible for doing approvals.
            //
            using (SPSite site = new SPSite(SqlM.GetEntry("Config", "ManagementURL")))
            {
                using (SPWeb adminWeb = site.OpenWeb())
                {
                    SPGroup SCApproveGroup = adminWeb.SiteGroups[SqlM.GetEntry("Config", "SCWorkflowApprovers")];
                    try
                    {
                        foreach (SPUser user in SCApproveGroup.Users)
                        {
                            if (user.Email != null && user.Email != "")
                            {
                                msg.To.Add(new MailAddress(user.Email));
                            }
                        }
                        msg.Subject = Resources.WorkflowCreatedMessageSubject;
                        msg.From = new MailAddress(SqlM.GetEntry("Config", "eMailSource"));
                        string mailMsg = String.Format(Resources.WorkflowCreatedMessageText, Values[3], Values[0], SqlM.GetEntry("Config", "ManagementURL"));
                        msg.Body = mailMsg;
                        SmtpClient client = new SmtpClient(SqlM.GetEntry("Config", "SMTPHost"));
                        client.Send(msg);
                    }
                    catch (Exception Ex)
                    {
                        TextLabel.Text += Resources.EmailFailedMessage;
                    }
                }
            }

            //
            // Restore the thread context.
            //
            objOriginalUser.Impersonate();

            TextLabel.Font.Bold = true;
            TextLabel.Text = String.Format(Resources.WorkflowCreatedMessage, HttpUtility.HtmlEncode(SiteTitle.Text));

            SiteTitle.Text = null;
            SiteURL.Text = null;
            SiteDesc.Text = null;
            Justification.Text = null;
        }

        private static void NewWorkflowItem(string[] Values)
        {

            // Regular users don't have access to the database, so run 
            // with elevated privileges. (Connects to DB as admin).
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {

                String dbConn = ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString;
                SqlConnection connection = new SqlConnection(
                                                   dbConn
                                                   );

                connection.Open();

                SqlCommand command = new SqlCommand(
                                               "INSERT INTO SiteProvision (SiteURL, SiteTitle, SiteDescription, Requester, RequestTimestamp, Justification, Status, Template) " +
                                               " VALUES (@v0, @v1, @v2, @v3, @v4, @v5, @v6, @v7)",
                                               connection
                                               );
                command.Parameters.Add("@v0", SqlDbType.NChar);
                command.Parameters.Add("@v1", SqlDbType.NChar);
                command.Parameters.Add("@v2", SqlDbType.NChar);
                command.Parameters.Add("@v3", SqlDbType.NChar);
                command.Parameters.Add("@v4", SqlDbType.NChar);
                command.Parameters.Add("@v5", SqlDbType.NChar);
                command.Parameters.Add("@v6", SqlDbType.NChar);
                command.Parameters.Add("@v7", SqlDbType.NChar);
                command.Parameters["@v0"].Value = Values[0];
                command.Parameters["@v1"].Value = Values[1];
                command.Parameters["@v2"].Value = Values[2];
                command.Parameters["@v3"].Value = Values[3];
                command.Parameters["@v4"].Value = Values[4];
                command.Parameters["@v5"].Value = Values[5];
                command.Parameters["@v6"].Value = Values[6];
                command.Parameters["@v7"].Value = Values[7];

                command.ExecuteNonQuery();
                connection.Close();
            });

        }
    }
}
